﻿using Garfield.Core;
using Garfield.Core.Runtime;

namespace Garfield.Runtime.Pico.Test
{
    class ExtensionPointHost : Plugin
    {
        public static ExtensionPoint<string> PrimaryType = DeclareExtensionPoint<string>(typeof(ExtensionPointHost), "PrimaryType", false);
        public static ExtensionPoint<string, int> NamedPrimaryType = DeclareExtensionPoint<string, int>(typeof(ExtensionPointHost), "NamedPrimaryType", false);
        public static ExtensionPoint<IExtension> ExtensionType = DeclareExtensionPoint<IExtension>(typeof(ExtensionPointHost), "ExtensionType", false);
        public static ExtensionPoint<string, IExtension> NamedExtensionType = DeclareExtensionPoint<string, IExtension>(typeof(ExtensionPointHost), "NamedExtensionType", false);

        public static ExtensionPoint<IExtensionRequiresService> ServiceBasedExtensions = DeclareExtensionPoint<IExtensionRequiresService>(typeof(ExtensionPointHost), "ServiceBasedExtensions", false);

        protected override void Initialize()
        {            
        }
    }

    interface IExtension { }

    class ExtensionImplementation : IExtension { }

    class InitializableExtension : IExtension { public string Property { get; set; } }

    interface IExtensionRequiresService
    {
        IService Service { get; }
    }

    class ExtensionRequireService : IExtensionRequiresService
    {
        public IService Service { get; private set; }

        public ExtensionRequireService(IService service)
        {
            Service = service;
        }
    }

    interface IService {}
    class Service : IService {}

    class ExtensionProvider : Plugin
    {
        protected override void Initialize()
        {
            Register(ExtensionPointHost.PrimaryType, "extension");
            Register(ExtensionPointHost.NamedPrimaryType, "extension.1", 1);
            Register(ExtensionPointHost.NamedPrimaryType, "extension.2", 2);

            Register(ExtensionPointHost.ExtensionType, Implementation<ExtensionImplementation>());
            Register(ExtensionPointHost.NamedExtensionType, "extension.1", Implementation<ExtensionImplementation>());

            Register(ExtensionPointHost.ServiceBasedExtensions, Implementation<ExtensionRequireService>());
        }
    }

    class ExtensionPointInjectViaConstructor
    {
        public ExtensionPointInjectViaConstructor([ExtensionPoint("PrimaryType")]IExtensionPoint<string> primaryTypes)
        {
            PrimaryTypes = primaryTypes;
        }

        public IExtensionPoint<string> PrimaryTypes { get; private set; }
    }

    class ExtensionPointInjectViaField
    {
        [ExtensionPoint("PrimaryType")]
        private IExtensionPoint<string> primaryTypes;

        public IExtensionPoint<string> PrimaryTypes
        {
            get { return primaryTypes; }            
        }
    }

    class ExtensionPointInjectViaProperty
    {
        [ExtensionPoint("PrimaryType")]
        public IExtensionPoint<string> PrimaryTypes { get; private set; }
    }

    class ServiceInjectViaField
    {
        [Service] private IService service;

        public IService Service
        {
            get { return service; }
            set { service = value; }
        }
    }


    class ServiceInjectViaProperty
    {
        [Service]
        public IService Service { get; private set; }
    }
}
